package edu.zjucst.spb.pkg.shiro.realm;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import edu.zjucst.spb.dao.branch.BranchDao;
import edu.zjucst.spb.dao.role.RoleDao;
import edu.zjucst.spb.dao.user.UserDao;
import edu.zjucst.spb.domain.entity.Branch;
import edu.zjucst.spb.domain.entity.Role;
import edu.zjucst.spb.domain.entity.SpbUser;
import edu.zjucst.spb.pkg.shiro.token.SPBUsernamePasswordToken;
import edu.zjucst.spb.util.SessionUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Optional;

/**
 * @author MrLi
 * @date 2023-02-17 17:11
 **/
@Slf4j
public class UsernamePasswordRealm extends AuthorizingRealm {
    @Autowired
    private UserDao userDao;
    @Autowired
    private BranchDao branchDao;
    @Autowired
    private RoleDao   roleDao;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        SPBUsernamePasswordToken token = (SPBUsernamePasswordToken) authenticationToken;
        log.info("{}用户进行密码登录", token.getUsername());
        Optional<SpbUser> spbUser = Optional.ofNullable(userDao.selectOne(new LambdaQueryWrapper<SpbUser>().eq(
            SpbUser::getUserNumber,
            token.getUsername()
        )));
        if (spbUser.isPresent()) {
            log.info("{}用户登录成功, data: {}", spbUser.get().getUserNumber(), JSONObject.toJSONString(spbUser.get()));
        } else {
            log.info("{}用户没找到", token.getUsername());
        }
        // 设置session
        spbUser.ifPresent(user -> {
            Optional<Branch> branch = Optional.ofNullable(branchDao.selectOne(new LambdaQueryWrapper<Branch>().eq(Branch::getBranchName, user.getPartyBranch())));
            branch.ifPresent(value -> SessionUtil.setBranchId(value.getId()));
            Optional<Role> role = Optional.ofNullable(roleDao.selectOne(new LambdaQueryWrapper<Role>().eq(Role::getRoleName, user.getRoleName())));
            role.ifPresent(value -> SessionUtil.setRoleId(value.getId()));
            SessionUtil.setUserId(user.getId());
        });
        // 如果为null, 则会
        return spbUser.map(value -> new SimpleAuthenticationInfo(token.getUsername(), value.getPwd(), getName())).orElse(null);
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 给subject进行授权
        System.out.println("密码授权ing..");
        Subject subject = SecurityUtils.getSubject();
        // 通过数据库来拿到 用户拥有的权限
        String username = (String) subject.getPrincipal();

        Optional<SpbUser> spbUser = Optional.ofNullable(userDao.selectOne(new LambdaQueryWrapper<SpbUser>().eq(
            SpbUser::getUserNumber,
            username
        )));

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRole(spbUser.map(SpbUser::getRoleName).orElse(""));
        return info;
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        return super.supports(token) && SPBUsernamePasswordToken.class.isAssignableFrom(token.getClass());
    }
}
